﻿using System;
using System.Linq;
using FluentValidation;
using FluentValidation.Results;
using GiveAQuiz.Data;
using GiveAQuiz.Web.Helpers;
using GiveAQuiz.Web.Models;

namespace GiveAQuiz.Web.Validation
{
  public class QuizPickerValidator : AbstractValidator<QuizPickerViewModel>
  {
    /// <summary>
    /// Creates a new instance of a QuizPickerValidator
    /// </summary>
    /// <param name="quizRepository">Used to query the underlying storage 
    /// for Quiz information.</param>
    public QuizPickerValidator(IQuizRepository quizRepository)
    {
      QuizRepository = quizRepository;

      RuleFor(m => m.TakerName).NotBlank().WithMessage("You must enter your name");
      RuleFor(m => m.QuizPassphrase).NotBlank().WithMessage("You must enter the quiz passphrase");
      RuleFor(m => m.EMail).NotBlank().WithMessage("You must enter your email address");
      RuleFor(m => m.EMail).EmailAddress().WithMessage("You must enter a valid email address");
    }

    public IQuizRepository QuizRepository
    {
      get; private set;
    }

    /// <summary>
    /// Validates an instance of a QuizPickerViewModel.
    /// </summary>
    /// <param name="instance">The QuizPickerViewModel instance to validate.</param>
    /// <returns>A ValidationResult containing any errors.</returns>
    public override ValidationResult Validate(QuizPickerViewModel instance)
    {
      var vr = base.Validate(instance);

      // base validates the QuizPassphrase for not null
      if ( !String.IsNullOrWhiteSpace(instance.QuizPassphrase) )
      {
        // search for the quiz by passphrase
        var quiz = QuizRepository.GetQuizByPassphrase(instance.QuizPassphrase);
        if (quiz != null)
        {
          var today = DateTime.Now;

          if ( today < quiz.StartDate )
          {
            vr.Errors.Add(new ValidationFailure("StartDate", "The quiz you requested has not yet started"));
          }
          if ( today > quiz.EndDate || quiz.HasEnded )
          {
            vr.Errors.Add(new ValidationFailure("EndDate", "The quiz you requested has already ended"));
          }
          // check to see if name is required
          if ( !quiz.IsNameOptional && String.IsNullOrWhiteSpace(instance.TakerName))
          {
            vr.Errors.Add(new ValidationFailure("TakerName", "You must enter your name"));
          }

          // make sure person hasn't taken this quiz before
          var quizTakerEmail =
            quiz.QuizResults
              .Select(qr => qr.QuizTaker)
              .FirstOrDefault(qt => String.CompareOrdinal(qt.EMail, instance.EMail) == 0);
          
          if ( quizTakerEmail != null )
          {
            vr.Errors.Add(new ValidationFailure("Email", "You cannot take this quiz since you have already taken it"));
          }
        }
        else
        {
          vr.Errors.Add(new ValidationFailure("QuizPassphrase", "There was no quiz found matching that passphrase"));
        }
      }

      return vr;
    }
   
  }
}
